﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using EventHandler.Libraries.Business.Security.Authentication;
using Rhino.Mocks;
using EventHandler.Libraries.Business.Security;
using System.Data;
using EventHandler.Libraries.Business.Database;

namespace EventHandler.Libraries.Business.Tests.Security.Authentication
{
    [TestFixture]
    public class DBAuthenticationProviderTest
    {
        [Test]
        public void LoginPassUsingDB()
        {
            var dbHelper = MockRepository.GenerateMock<IDatabaseHelper>();
            DBAuthenticationProvider dbProvider = new DBAuthenticationProvider(dbHelper,"username","password");
            
            var cn = MockRepository.GenerateMock<IDbConnection>();
            dbHelper.Expect(x => x.GetConnection()).Return(cn);

            var cmd = MockRepository.GenerateMock<IDbCommand>();
            cn.Expect(x => x.CreateCommand()).Return(cmd);

            cmd.Expect(x => x.CommandType).PropertyBehavior();
            cmd.Expect(x => x.CommandText).PropertyBehavior();

            var username = MockRepository.GenerateMock<IDbDataParameter>();
            cmd.Expect(x=>x.CreateParameter()).Return(username);
            username.Expect(x => x.Size).PropertyBehavior();
            username.Expect(x => x.ParameterName).PropertyBehavior();
            username.Expect(x => x.DbType).PropertyBehavior();

            var password = MockRepository.GenerateMock<IDbDataParameter>();
            cmd.Expect(x=>x.CreateParameter()).Return(password);
            password.Expect(x => x.Size).PropertyBehavior();
            password.Expect(x => x.ParameterName).PropertyBehavior();
            password.Expect(x => x.DbType).PropertyBehavior();

            var parameters = MockRepository.GenerateMock<IDataParameterCollection>();

            cmd.Expect(x => x.Parameters).Return(parameters).Repeat.Twice();

            var dataReader = MockRepository.GenerateMock<IDataReader>();
            cmd.Expect(x => x.ExecuteReader()).Return(dataReader);
            dataReader.Expect(x => x.Read()).Return(true);

            Authenticator auth = new Authenticator(dbProvider);
            bool loginSuccessful = auth.Login();

            Assert.AreEqual(CommandType.StoredProcedure,cmd.CommandType);
            Assert.AreEqual("Auth.VerifyAccount", cmd.CommandText);

            Assert.AreEqual(255, username.Size);
            Assert.AreEqual(255, password.Size);
            Assert.AreEqual("@Username", username.ParameterName);
            Assert.AreEqual("@Password", password.ParameterName);
            Assert.AreEqual(DbType.String, username.DbType);
            Assert.AreEqual(DbType.String, password.DbType);


            cn.AssertWasCalled(x => x.Open());
            cn.AssertWasCalled(x => x.Close());
            parameters.AssertWasCalled(x => x.Add(username));
            parameters.AssertWasCalled(x => x.Add(password));

            Assert.IsTrue(loginSuccessful);
        }

        [Test]
        public void LoginFailUsingDB()
        {
            var dbHelper = MockRepository.GenerateMock<IDatabaseHelper>();
            DBAuthenticationProvider dbProvider = new DBAuthenticationProvider(dbHelper, "username", "password");

            var cn = MockRepository.GenerateMock<IDbConnection>();
            dbHelper.Expect(x => x.GetConnection()).Return(cn);

            var cmd = MockRepository.GenerateMock<IDbCommand>();
            cn.Expect(x => x.CreateCommand()).Return(cmd);

            cmd.Expect(x => x.CommandType).PropertyBehavior();
            cmd.Expect(x => x.CommandText).PropertyBehavior();

            var username = MockRepository.GenerateMock<IDbDataParameter>();
            cmd.Expect(x => x.CreateParameter()).Return(username);
            username.Expect(x => x.Size).PropertyBehavior();
            username.Expect(x => x.ParameterName).PropertyBehavior();
            username.Expect(x => x.DbType).PropertyBehavior();

            var password = MockRepository.GenerateMock<IDbDataParameter>();
            cmd.Expect(x => x.CreateParameter()).Return(password);
            password.Expect(x => x.Size).PropertyBehavior();
            password.Expect(x => x.ParameterName).PropertyBehavior();
            password.Expect(x => x.DbType).PropertyBehavior();

            var parameters = MockRepository.GenerateMock<IDataParameterCollection>();

            cmd.Expect(x => x.Parameters).Return(parameters).Repeat.Twice();

            var dataReader = MockRepository.GenerateMock<IDataReader>();
            cmd.Expect(x => x.ExecuteReader()).Return(dataReader);
            dataReader.Expect(x => x.Read()).Return(false);

            Authenticator auth = new Authenticator(dbProvider);
            bool loginSuccessful = auth.Login();

            Assert.AreEqual(CommandType.StoredProcedure, cmd.CommandType);
            Assert.AreEqual("Auth.VerifyAccount", cmd.CommandText);

            Assert.AreEqual(255, username.Size);
            Assert.AreEqual(255, password.Size);
            Assert.AreEqual("@Username", username.ParameterName);
            Assert.AreEqual("@Password", password.ParameterName);
            Assert.AreEqual(DbType.String, username.DbType);
            Assert.AreEqual(DbType.String, password.DbType);


            cn.AssertWasCalled(x => x.Open());
            cn.AssertWasCalled(x => x.Close());
            parameters.AssertWasCalled(x => x.Add(username));
            parameters.AssertWasCalled(x => x.Add(password));

            Assert.IsFalse(loginSuccessful);
        }
    }
}
